package com.pan.api.utils;


import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Function;


enum PanApiDocXmlUtilImpl implements PanApiDocXmlUtil {
    INSTANCE;
    private Element rootElement;

    PanApiDocXmlUtilImpl() {
        ClassLoader classLoader = PanApiDocXmlUtilImpl.class.getClassLoader();
        InputStream configInputStream = classLoader.getResourceAsStream("PanApiDoc.xml");
        DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
        DocumentBuilder documentBuilder = null;
        try {
            documentBuilder = documentBuilderFactory.newDocumentBuilder();
            Document document = documentBuilder.parse(configInputStream);
            document.normalizeDocument();
            rootElement = document.getDocumentElement();
        } catch (SAXException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        } catch (ParserConfigurationException e) {
            throw new RuntimeException(e);
        }
    }


    private Function<Node, Boolean> isElement = node -> node.getNodeType() == Node.ELEMENT_NODE;

    @Override
    public List<Element> find(Element element, String tagName) {
        NodeList nodeList = element.getElementsByTagName(tagName);
        List<Element> elementList = new ArrayList<>();
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (isElement.apply(node)) {
                elementList.add((Element) node);
            }
        }
        return elementList;
    }

    @Override
    public List<Element> find(String tagName) {
        return find(rootElement, tagName);
    }

    @Override
    public Element findFirst(Element element, String... tagNames) {
        for (String tagName: tagNames){
            List<Element> elementList = find(element, tagName);
            if (elementList.size() == 0) throw new RuntimeException("No Such Element by tagName: "+tagName);
            element = elementList.get(0);
        }
        return element;
    }

    @Override
    public Element findFirst(String... tagNames) {
        return findFirst(rootElement, tagNames);
    }

}
